﻿//C++支持内置类型隐式类型转换为类类型对象，需要有相关内置类型为参数的构造函数。
//构造函数前面加explicit就不再支持隐式类型转换。
//类类型的对象之间也可以隐式转换，需要相应的构造函数支持

//C语言的类型转换
//整形之间   整数和浮点数之间    整形和指针之间    指针和指针之间


#include<iostream>
using namespace std;
class A
{
public:
	// 构造函数explicit就不再支持隐式类型转换
	// explicit A(int a1)
	A(int a1)
		:_a1(a1)
	{
	}
	//explicit A(int a1, int a2)
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{
	}

	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
	int Get() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 2;
};

class B
{
public:
	B(const A& a)
		:_b(a.Get())
	{
	}
private:
	int _b = 0;
};

int main()
{
	// 1构造⼀个A的临时对象，再用这个临时对象拷贝构造aa3
	// 编译器遇到连续构造+拷贝构造->优化为直接构造
	A aa1 = 1;
	aa1.Print();
	const A& aa2 = 1;

	// C++11之后才支持多参数转化
	A aa3 = { 2,2 };
	// aa3隐式类型转换为b对象
	// 原理跟上面类似
	B b = aa3;
	const B& rb = aa3;
	return 0;
}

//为什么aa2要使用const修饰
//	在代码中，我们试图用一个整数1来初始化一个A类的常量引用aa。这里会发生隐式转换：整数1会被用来构造一个临时的A对象（通过调用A的构造函数A(int)）。
//	临时对象通常是一个右值（rvalue），它的生命周期通常是短暂的，只存在于创建它的表达式期间。但是C++标准有一个特殊的规则：
//当我们将一个临时对象绑定到一个常量引用（const reference）上时，临时对象的生命周期会被延长，与这个引用的生命周期相同。
//	因此，使用const引用可以安全地持有这个临时对象，在main函数结束前，这个临时对象都不会被销毁。
//	如果使用非常量引用（non - const reference），则不允许绑定到临时对象（右值）上。
//因为非常量引用意味着可能修改这个对象，而临时对象是即将销毁的，允许修改一个临时对象通常是没有意义的（而且容易导致错误）。
//所以C++语言标准规定，非const引用不能绑定到右值（临时对象）。
//	因此，在代码中，必须使用const引用（const A & ）来绑定由整数1隐式转换生成的临时A对象。
//	总结：
//	- 临时对象（右值）可以绑定到const引用，并且会延长临时对象的生命周期。
//	- 临时对象不能绑定到非const引用，因为非const引用只能绑定到左值（有名字的对象）。
//
//	C++11引入了右值引用（&&），可直接绑定临时对象（如A&& aa = 1;），但此处问题不涉及。




